package com.milling.business.service.impl;

import com.milling.business.BusinessConstants;
import com.milling.business.domain.WmsNeedleCache;
import com.milling.business.mapper.WmsNeedleCacheMapper;
import com.milling.business.service.IWmsNeedleCacheService;
import com.milling.common.core.redis.RedisCache;
import com.milling.common.utils.DateUtils;
import com.milling.common.utils.StringUtils;
import com.milling.common.utils.modbus.ModbusMasterPoolFactory;
import com.milling.common.utils.modbus.ModbusServiceFactory;
import com.milling.common.utils.modbus.ModbusTcpService;
import com.milling.common.utils.modbus.ModbusTcpServiceImpl;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import org.apache.commons.pool2.ObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 配针缓存区Service业务层处理
 *
 * @author X
 * @date 2025-02-04
 */
@Service
public class WmsNeedleCacheServiceImpl implements IWmsNeedleCacheService
{

    private static final Logger logger = LoggerFactory.getLogger(WmsNeedleCacheServiceImpl.class);

    @Autowired
    private WmsNeedleCacheMapper wmsNeedleCacheMapper;

    @Autowired
    private RedisCache redisCache;

    @Value("${modbus.tcp.host:192.168.237.88}") // 默认值防止未配置
    private String host;

    @Value("${modbus.tcp.port:502}")
    private int port;

    @Value("${modbus.tcp.poolSize:5}")
    private int poolSize;

    @Value("${modbus.tcp.slaveId:1}")
    private int slaveId;

    // 获取Modbus服务实例
    private ModbusTcpService modbusTcpService;

    // 添加初始化方法
    @PostConstruct
    public void init() {
        // 初始化 Modbus 服务
        modbusTcpService = ModbusServiceFactory.getModbusService(host, port, poolSize);
        logger.info("WmsNeedleCacheServiceImpl Modbus服务初始化完成 - {}:{}", host, port);

        // 初始化扫码器连接
//        initConnection();
    }
    /**
     * 查询配针缓存区
     *
     * @param needleId 配针缓存区主键
     * @return 配针缓存区
     */
    @Override
    public WmsNeedleCache selectWmsNeedleCacheByNeedleId(Long needleId)
    {
        return wmsNeedleCacheMapper.selectWmsNeedleCacheByNeedleId(needleId);
    }

    /**
     * 查询配针缓存区列表
     *
     * @param wmsNeedleCache 配针缓存区
     * @return 配针缓存区
     */
    @Override
    public List<WmsNeedleCache> selectWmsNeedleCacheList(WmsNeedleCache wmsNeedleCache)
    {
        return wmsNeedleCacheMapper.selectWmsNeedleCacheList(wmsNeedleCache);
    }

    /**
     * 新增配针缓存区
     *
     * @param wmsNeedleCache 配针缓存区
     * @return 结果
     */
    @Override
    public int insertWmsNeedleCache(WmsNeedleCache wmsNeedleCache)
    {
        String drillInfo = wmsNeedleCache.getDrillInfo();
        String drillSize = drillInfo.substring(0, 4);
        String drillType = drillInfo.substring(4, 5);
        String drillGrindCount = drillInfo.substring(7, 8);
        wmsNeedleCache.setDrillType(drillType);
        wmsNeedleCache.setDrillSize(drillSize);
        wmsNeedleCache.setDrillGrindCount(new Long(drillGrindCount));
        wmsNeedleCache.setDrillFactory("1");
        wmsNeedleCache.setDrillEdge("1");
        wmsNeedleCache.setCreateTime(DateUtils.getNowDate());
        return wmsNeedleCacheMapper.insertWmsNeedleCache(wmsNeedleCache);
    }

    /**
     * 修改配针缓存区
     *
     * @param wmsNeedleCache 配针缓存区
     * @return 结果
     */
    @Override
    public int updateWmsNeedleCache(WmsNeedleCache wmsNeedleCache)
    {
        String drillInfo = wmsNeedleCache.getDrillInfo();
        String drillSize = drillInfo.substring(0, 4);
        String drillType = drillInfo.substring(4, 5);
        String drillGrindCount = drillInfo.substring(7, 8);
        wmsNeedleCache.setDrillType(drillType);
        wmsNeedleCache.setDrillSize(drillSize);
        wmsNeedleCache.setDrillGrindCount(new Long(drillGrindCount));
        wmsNeedleCache.setDrillFactory("1");
        wmsNeedleCache.setDrillEdge("1");
        wmsNeedleCache.setUpdateTime(DateUtils.getNowDate());
        return wmsNeedleCacheMapper.updateWmsNeedleCache(wmsNeedleCache);
    }

    /**
     * 批量删除配针缓存区
     *
     * @param needleIds 需要删除的配针缓存区主键
     * @return 结果
     */
    @Override
    public int deleteWmsNeedleCacheByNeedleIds(Long[] needleIds)
    {
        return wmsNeedleCacheMapper.deleteWmsNeedleCacheByNeedleIds(needleIds);
    }

    /**
     * 删除配针缓存区信息
     *
     * @param needleId 配针缓存区主键
     * @return 结果
     */
    @Override
    public int deleteWmsNeedleCacheByNeedleId(Long needleId)
    {
        return wmsNeedleCacheMapper.deleteWmsNeedleCacheByNeedleId(needleId);
    }

    /**
     * 更新配针盘位置状态  暂时废除
     */
    @Override
    public void syncNeeldStatusA()
    {
        //通过REDIS，刷新NEEDLE配针缓存区数据
        logger.info("#############更新配针盘位置状态任务处理开始####");
        long startTime = System.currentTimeMillis(); // 记录开始时间
        List<WmsNeedleCache> cacheList = wmsNeedleCacheMapper.selectWmsNeedleCacheList(new WmsNeedleCache());

        // 创建连接池
//        ObjectPool<ModbusMaster> modbusMasterPool = ModbusMasterPoolFactory.createPool(host, port, poolSize);
//
//        // 创建ModbusService实例
//        ModbusTcpService modbusTcpService = new ModbusTcpServiceImpl(modbusMasterPool);

//        启动，告知上料托盘数量  暂时写为1


        try {
            for (int i = 0; i < cacheList.size(); i++) {
                WmsNeedleCache wmsNeedleCache = cacheList.get(i);
                int needleCount = modbusTcpService.readHoldingRegister(slaveId, (4699 + wmsNeedleCache.getNeedleId().intValue()));
                if(needleCount > 0) {
                    //状态   有货
                    if(BusinessConstants.NEEDLE_STATUS_1.equals(wmsNeedleCache.getStatus())) {
                        wmsNeedleCache.setStatus(BusinessConstants.NEEDLE_STATUS_2);
                    }
                    wmsNeedleCache.setDrillCount(new Long(needleCount));
                    wmsNeedleCache.setUpdateTime(DateUtils.getNowDate());
                } else {
                    //清空配针缓存位数据，状态  空闲
                    wmsNeedleCache.setStatus(BusinessConstants.NEEDLE_STATUS_1);
                    wmsNeedleCache.setDrillSize(null);
                    wmsNeedleCache.setDrillInfo(null);
                    wmsNeedleCache.setDrillType(null);
                    wmsNeedleCache.setDrillEdge(null);
                    wmsNeedleCache.setDrillFactory(null);
                    wmsNeedleCache.setDrillGrindCount(null);
                    wmsNeedleCache.setDrillCount(new Long(0));
                    wmsNeedleCache.setUpdateTime(DateUtils.getNowDate());
                    //其他数据暂不清除
                }
                wmsNeedleCacheMapper.updateWmsNeedleCache(wmsNeedleCache);
            }
        } catch (ModbusTransportException ex) {
            ex.printStackTrace();
//            throw new RuntimeException(ex);
        } catch (Exception e) {
            e.printStackTrace();
        }


        logger.info("#############更新配针盘位置状态任务处理结束");
        long endTime = System.currentTimeMillis(); // 记录结束时间
        long duration = endTime - startTime; // 计算执行时间
        logger.info("method[runTask] executed in {} ms", duration); // 输出执行时间
    }

    @Override
    public void sysncNeedleStatus() {
        logger.info("#######配针缓存区数据同步处理开始####");
        long startTime = System.currentTimeMillis(); // 记录开始时间

/*
        for (int i = 4700; i <= 4796; i++) {
            String key = "NEEDLE_ID" + (i-4699);
            int value = modbusUtil.readHoldingRegister(i);
            logger.info("key is" + key + "|读取到的值：" + value);
            redisCache.setCacheObject(key, value);
        }
*/
//        ObjectPool<ModbusMaster> modbusMasterPool = ModbusMasterPoolFactory.createPool(host, port, poolSize);
//        // 创建ModbusService实例
//        ModbusTcpService modbusTcpService = new ModbusTcpServiceImpl(modbusMasterPool);
        Map needleStockMap = new HashMap();

        try{
            short[] registers = modbusTcpService.readHoldingRegisters(slaveId, 4700, 84);
            for (int i = 1; i <= 84; i++) {
                String key = "NEEDLE_ID" + (i);
                int value = registers[(i-1)];
//                logger.info("key: " + key + " || value: " + value);
                needleStockMap.put(key, value);
            }
        } catch (ModbusTransportException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
//        } finally {
//            modbusMasterPool.close();
        }

        //通过REDIS，刷新NEEDLE配针缓存区数据
        List<WmsNeedleCache> cacheList = wmsNeedleCacheMapper.selectWmsNeedleCacheList(new WmsNeedleCache());

        // 按needleId排序，确保索引对应正确
        cacheList.sort((a, b) -> a.getNeedleId().compareTo(b.getNeedleId()));

        for (int i = 0; i < cacheList.size(); i++) {
            WmsNeedleCache wmsNeedleCache = cacheList.get(i);
            Long needleId = wmsNeedleCache.getNeedleId();

            // 🔧 修复关键Bug：使用实际的needleId作为键，而不是数组索引
            String key = "NEEDLE_ID" + needleId;
            Integer needleCountObj = (Integer) needleStockMap.get(key);
            int needleCount = (needleCountObj != null) ? needleCountObj : 0;

            String currentStatus = wmsNeedleCache.getStatus();
            Long currentCount = wmsNeedleCache.getDrillCount();

            logger.debug("配针缓存位 {} - PLC数量: {}, DB数量: {}, 状态: {}",
                    needleId, needleCount, currentCount, currentStatus);

            if (needleCount == 0) {
                // 只有当前不是业务处理状态时才清空
                if (BusinessConstants.NEEDLE_STATUS_1.equals(currentStatus) ||
                        BusinessConstants.NEEDLE_STATUS_2.equals(currentStatus)) {
                    logger.info("配针缓存位 {} PLC数量为0，清空数据，状态改为空闲", needleId);
                    //清空配针缓存位数据，状态  空闲
                    wmsNeedleCache.setStatus(BusinessConstants.NEEDLE_STATUS_1);
                    wmsNeedleCache.setDrillSize(null);
                    wmsNeedleCache.setDrillInfo(null);
                    wmsNeedleCache.setDrillType(null);
                    wmsNeedleCache.setDrillEdge(null);
                    wmsNeedleCache.setDrillFactory(null);
                    wmsNeedleCache.setDrillGrindCount(null);
                    wmsNeedleCache.setDrillCount(0L);
                    wmsNeedleCache.setUpdateTime(DateUtils.getNowDate());
                } else {
                    logger.info("配针缓存位 {} PLC数量为0，但当前状态为 {}，不清空数据", needleId, currentStatus);
                    // 只更新数量，不改变状态和其他数据
                    wmsNeedleCache.setDrillCount(0L);
                    wmsNeedleCache.setUpdateTime(DateUtils.getNowDate());
                }
            } else {
                //状态   有货 - 但需要考虑当前状态，避免覆盖正在进行的业务状态
                // 只有在空闲状态时才更新为有货状态，避免覆盖业务流程中的状态
                if(BusinessConstants.NEEDLE_STATUS_1.equals(currentStatus)) {
                    wmsNeedleCache.setStatus(BusinessConstants.NEEDLE_STATUS_2);
                    logger.info("配针缓存位 {} 状态从空闲更新为有货，数量: {}", needleId, needleCount);
                } else if (BusinessConstants.NEEDLE_STATUS_2.equals(currentStatus)) {
                    // 已经是有货状态，只更新数量
                    if (currentCount == null || !currentCount.equals((long)needleCount)) {
                        logger.info("配针缓存位 {} 保持有货状态，数量更新: {} -> {}", needleId, currentCount, needleCount);
                    }
                } else {
                    // 其他状态（回流中、补料中等）不做状态更新，只记录日志
                    logger.debug("配针缓存位 {} 当前状态为 {}，跳过状态更新，仅更新数量: {}",
                            needleId, currentStatus, needleCount);
                }
                wmsNeedleCache.setDrillCount((long)needleCount);
                wmsNeedleCache.setUpdateTime(DateUtils.getNowDate());

/*              数量直接从数据库读取，不使用缓存
                int cacheCount = 0;
                String key = wmsNeedleCache.getDrillInfo() + "-COUNT";
                Integer cacheValue = (Integer)redisCache.getCacheObject(key);
                if(StringUtils.isNotEmpty(wmsNeedleCache.getDrillInfo()) && null != cacheValue) {
                    cacheCount = cacheValue.intValue();
                }

                if(cacheCount >= 0 && needleCount > 0 && StringUtils.isNotEmpty(wmsNeedleCache.getDrillInfo())) {
                    int value = cacheCount + needleCount;
                    redisCache.setCacheObject(key, value);
                    logger.info("料号数量缓存：" + key + "，值：" + value);
                }
*/
            }
            wmsNeedleCacheMapper.updateWmsNeedleCache(wmsNeedleCache);
        }

        logger.info("#######配针缓存区数据同步处理结束");
        long endTime = System.currentTimeMillis(); // 记录结束时间
        long duration = endTime - startTime; // 计算执行时间
        logger.info("method[handlerTask] executed in {} ms", duration); // 输出执行时间
    }

    public List<Map> selectNeedleStock(WmsNeedleCache wmsNeedleCache) {
        return wmsNeedleCacheMapper.selectNeedleStock(wmsNeedleCache);
    }

    /**
     * 验证和修复状态不一致问题
     */
    public void validateAndFixStatusInconsistency() {
        logger.info("开始验证和修复配针缓存状态不一致问题...");

        try {
            // 读取PLC实际数据
            short[] registers = modbusTcpService.readHoldingRegisters(slaveId, 4700, 84);
            Map<String, Integer> plcDataMap = new HashMap<>();
            for (int i = 1; i <= 84; i++) {
                String key = "NEEDLE_ID" + i;
                int value = registers[i-1];
                plcDataMap.put(key, value);
            }

            // 查询数据库状态
            List<WmsNeedleCache> cacheList = wmsNeedleCacheMapper.selectWmsNeedleCacheList(new WmsNeedleCache());

            int inconsistencyCount = 0;
            for (WmsNeedleCache cache : cacheList) {
                String key = "NEEDLE_ID" + cache.getNeedleId();
                Integer plcCount = plcDataMap.get(key);
                if (plcCount == null) plcCount = 0;

                Long dbCount = cache.getDrillCount();
                if (dbCount == null) dbCount = 0L;
                String status = cache.getStatus();

                boolean isInconsistent = false;
                String issue = "";

                // 检查数量和状态的一致性
                if (plcCount == 0 && !"1".equals(status)) {
                    isInconsistent = true;
                    issue = "PLC无料但DB状态不是空闲";
                } else if (plcCount > 0 && "1".equals(status)) {
                    isInconsistent = true;
                    issue = "PLC有料但DB状态是空闲";
                } else if (!plcCount.equals(dbCount.intValue())) {
                    isInconsistent = true;
                    issue = "PLC数量与DB数量不一致";
                }

                if (isInconsistent) {
                    inconsistencyCount++;
                    logger.warn("配针位 {} 状态不一致 - {}: PLC数量={}, DB数量={}, DB状态={}",
                            cache.getNeedleId(), issue, plcCount, dbCount, status);
                }
            }

            logger.info("状态验证完成，发现 {} 处不一致", inconsistencyCount);

        } catch (Exception e) {
            logger.error("验证状态一致性时发生异常", e);
        }
    }

}
